/*

	Simply reads from a file and prints the output, via a callback

*/

#include <systemSafeCall.h>
#include <cudaSafeCall.h>
#include <cudaParams.h>
#include <cudaParamCreate.h>
#include <cudaCallFunc.h>
#include <cstdio>
#include <pthread.h>
#include <sched.h>

#ifndef _WIN32
  #define __cdecl
#endif

extern "C"
{
  void __cdecl fileOpsMarshall(void * retPtr, void * params[])
  {

	printf("fileOpsMarshall() : About to read file.\n");
    FILE *fp = NULL;

	char* fname="hello.txt";

    if (fopen_s(&fp, fname, "r")!=0)
    {
        printf("fileOpsMarshall() : Failed to open file: %s\n", fname);
		fflush(stdout);
        return;
    }

#define MESGSIZE 20
	char mesg[MESGSIZE];

    if (fgets(mesg, MESGSIZE-1, fp) == NULL)
    {
		printf("fileOpsMarshall() : Failed to read from file: hello.txt\n");
		fflush(stdout);		
        return;
    }
    mesg[MESGSIZE-1]='\0';
	printf("fileOpsMarshall() : \tRead \"%s\" from %s.\n", mesg, fname);
  }
}

__global__ void mainKernel(cudaCallbackData * cdata, cudaHostFunction_t fileFunc)
{
  cudaCallFunc<int>(cdata, fileFunc, 0.0f, 3, 'a');
  cudaCallFunc<int>(cdata, fileFunc, 1.0f, 4, 'b');
  cudaCallFunc<int>(cdata, fileFunc, 2.0f, 5, 'c');
}

int main(int argc, char ** argv)
{
  dim3 gs = dim3(2, 1, 1);
  dim3 bs = dim3(1, 1, 1);

  cudaParamType_t returnParam;
  cudaParamType_t params[3];
  cudaHostFunction_t fileFunc;

  cudaCallbackData_t * callbackData;

  CUDA_SAFE_CALL(cudaSetDeviceFlags(cudaDeviceMapHost));
  CUDA_SAFE_CALL(cudaSetDevice(0));
  CUDA_SAFE_CALL(cudaHostCallbackInit(&callbackData));

  CUDA_SAFE_CALL(cudaParamCreate<int>(&returnParam));
  CUDA_SAFE_CALL(cudaParamCreate<float> (params + 0));
  CUDA_SAFE_CALL(cudaParamCreate<int>   (params + 1));
  CUDA_SAFE_CALL(cudaParamCreate<char>  (params + 2));
  CUDA_SAFE_CALL(cudaCreateHostFunc(&fileFunc, (void * )fileOpsMarshall, returnParam, 3, params));

  mainKernel<<<1, 1, 0, 0>>>(callbackData, fileFunc);
  CUDA_SAFE_CALL(cudaCallbackSynchronize(0));
  return 0;
}
